package control;

import view.Vista;
import model.Matriz;
import model.PhiKsi;
import model.SistemaLinear;

public class Main {

	public static void main(String[] args) {
		double valorGauss[]=new double[2];
		int neq=15;
		int nel,equacao;
		int[] numeroGlobal=new int[4];
		Matriz temp2,matrizLocal,matrizProdutoPhi,matrizGlobal,eq,Q,J,LG,coordenadasMalha,X,N;
		Matriz contorno,fLocal,fLocal1,fLocal2,fGlobal,fonteLocal,p,q,f,phi1;
		Vista v;
		
		//entrada
		LG=Leitura.lerLG();
		nel=LG.getN();
		eq=Leitura.lerEQ();
		contorno=Leitura.lerContorno();
		coordenadasMalha=Leitura.lerCoordenadas();
		f=Leitura.lerF();
		
		matrizGlobal=new Matriz(neq,neq);
		
		Q=new Matriz(2,2);
		J=new Matriz(2,2);
		
		valorGauss[0]=-Math.sqrt(3)/3;
		valorGauss[1]=Math.sqrt(3)/3;
		
		fLocal=new Matriz(4,1);
		fLocal1=new Matriz(4,1);
		fLocal2=new Matriz(4,1);
		fGlobal=new Matriz(neq,1);
		fonteLocal=new Matriz(4,1);
		p=new Matriz(4,1);
		q=new Matriz(4,1);
		
		phi1=new Matriz(4);
		
		for(int i=0;i<nel;i++){
			//calcular matriz local
	
			matrizLocal=new Matriz(4,4);
			matrizProdutoPhi=new Matriz(4,4);
			
			X=new Matriz(4,2);
			X.setValor(0, 0, coordenadasMalha.getValor(0,(int)LG.getValor(0, i)));
			X.setValor(0, 1, coordenadasMalha.getValor(1,(int)LG.getValor(0, i)));
			X.setValor(1, 0, coordenadasMalha.getValor(0,(int)LG.getValor(1, i)));
			X.setValor(1, 1, coordenadasMalha.getValor(1,(int)LG.getValor(1, i)));
			X.setValor(2, 0, coordenadasMalha.getValor(0,(int)LG.getValor(2, i)));
			X.setValor(2, 1, coordenadasMalha.getValor(1,(int)LG.getValor(2, i)));
			X.setValor(3, 0, coordenadasMalha.getValor(0,(int)LG.getValor(3, i)));
			X.setValor(3, 1, coordenadasMalha.getValor(1,(int)LG.getValor(3, i)));
			
			N=new Matriz(2,4);
			
			Q.setValor(0, 0, 1);
			Q.setValor(0, 1, 0);
			Q.setValor(1, 0, 0);
			Q.setValor(1, 1, 1);
			
			//ponto de gauss [j,k]
			for(int j=0;j<2;j++){
				for(int k=0;k<2;k++){
					
					N.setValor(0, 0,(PhiKsi.derivada(0, false, valorGauss[j], valorGauss[k])));
					N.setValor(0, 1,(PhiKsi.derivada(1, false, valorGauss[j], valorGauss[k])));
					N.setValor(0, 2,(PhiKsi.derivada(2, false, valorGauss[j], valorGauss[k])));
					N.setValor(0, 3,(PhiKsi.derivada(3, false, valorGauss[j], valorGauss[k])));
					N.setValor(1, 0,(PhiKsi.derivada(0, true, valorGauss[j], valorGauss[k])));
					N.setValor(1, 1,(PhiKsi.derivada(1, true, valorGauss[j], valorGauss[k])));
					N.setValor(1, 2,(PhiKsi.derivada(2, true, valorGauss[j], valorGauss[k])));
					N.setValor(1, 3,(PhiKsi.derivada(3, true, valorGauss[j], valorGauss[k])));
					
					J=Matriz.multiplicacao(N,X);
					
					temp2=Matriz.multiplicacao(N.transposta(), J.inversa().transposta());
					temp2=Matriz.multiplicacao(temp2, Q);
					temp2=Matriz.multiplicacao(temp2, J.inversa());
					temp2=Matriz.multiplicacao(temp2, N);
					temp2.escala(J.determinanteQuadrada());
					matrizLocal=Matriz.soma(matrizLocal, temp2);
					
					phi1.setValor(0, PhiKsi.imagem(0, valorGauss[j], valorGauss[k]));
					phi1.setValor(1, PhiKsi.imagem(1, valorGauss[j], valorGauss[k]));
					phi1.setValor(2, PhiKsi.imagem(2, valorGauss[j], valorGauss[k]));
					phi1.setValor(3, PhiKsi.imagem(3, valorGauss[j], valorGauss[k]));
					temp2=Matriz.multiplicacao(phi1, phi1.transposta());
					temp2.escala(J.determinanteQuadrada());
					matrizProdutoPhi=Matriz.soma(matrizProdutoPhi, temp2);
				}
			}
			
			//add na matriz global
			int a,b;
			for(int j=0;j<4;j++){
				for(int k=0;k<4;k++){
					a=(int)eq.getValor((int)LG.getValor(j, i));
					b=(int)eq.getValor((int)(LG.getValor(k, i)));
					if(a!=-1 && b !=-1){
						matrizGlobal.setValor(a, b, matrizLocal.getValor(j, k)+matrizGlobal.getValor(a, b));
					}
				}
			}
			
			for(int j=0;j<4;j++){
				numeroGlobal[j]=(int)LG.getValor(j, i);
				fonteLocal.setValor(j,0,f.getValor(numeroGlobal[j]));
				p.setValor(j,0,contorno.getValor(0,numeroGlobal[j]));
				q.setValor(j,0,contorno.getValor(1,numeroGlobal[j]));
			}
				
			//calcular fLocal1
			fLocal1=Matriz.multiplicacao(matrizProdutoPhi, fonteLocal);
				
			//calcular fLocal2
			fLocal2=Matriz.multiplicacao(matrizLocal, p);
				
			//calcular vetor local
			fLocal2.escala(-1);
			fLocal=Matriz.soma(fLocal1, fLocal2);
				
			for(int j=0;j<4;j++){
				equacao=(int)eq.getValor(numeroGlobal[j]);
				if(equacao!=-1){
					fGlobal.setValor(equacao, 0, fGlobal.getValor(equacao, 0)+fLocal.getValor(j, 0));
				}
			}
		}

		v=new Vista();
		Matriz c=SistemaLinear.ElinacaoGaussiana(matrizGlobal, fGlobal);
		v.addMatrizTexto(c);
		v.exibir();
	}
}
